/**
 * JAVACC DEMO 1.0
 */
package com.apache.info.service.plugins;

import com.apache.api.manager.PluginConnector;
import com.apache.api.vo.ParamsVo;
import com.apache.api.vo.ResultEntity;
import com.apache.cache.util.Validator;
import com.apache.database.db.IDao;
import com.apache.database.model.MethodParam;
import com.apache.info.entity.PubMetadata;
import com.apache.info.entity.PubSortInfo;
import com.apache.info.manager.InfoReleaseManager;
import com.apache.info.util.InfoMap;
import com.apache.info.util.MessageUtil;
import com.apache.tools.StrUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;

/**
 * description:  子表操作接口父类
 *
 * @author iussoft 创建时间：2016-10-15
 */
public abstract class AbstractSubInfoPlugin implements PluginConnector {

	private IDao pubMetadataDao;

	protected InfoReleaseManager InfoReleaseManager;

	private Logger log = LoggerFactory.getLogger(AbstractSubInfoPlugin.class);

	/**
	 * TODO 简单描述该方法的实现功能（可选）.
	 *
	 * @see PluginConnector#execute(ParamsVo)
	 */
	public Object execute(ParamsVo vo) throws Exception {
		ResultEntity entity = new ResultEntity();
		entity.setResult("true");
		String mainSortCode = String.valueOf(vo.getParams("mainSortCode"));
		String subSortCode = String.valueOf(vo.getParams("subSortCode"));
		String sysName = String.valueOf(vo.getParams("sysName"));
		ParamsVo pvo = new ParamsVo();
		if (Validator.isNotNull(mainSortCode) && Validator.isNotNull(subSortCode)) {
			String cacheKey = "pubSortInfo_";
			MethodParam param = new MethodParam("BySortCode", cacheKey + mainSortCode, "", PubSortInfo.class.getName());
			param.setParams("sysName", StrUtil.doNull(sysName, "plateform"));
			param.setParams("sortCode", mainSortCode);
			PubSortInfo sort = (PubSortInfo) pubMetadataDao.selectSingle(param);//获取主表信息

			param.setCacheId(cacheKey + subSortCode);
			param.setParams("sortCode", subSortCode);
			PubSortInfo subSort = (PubSortInfo) pubMetadataDao.selectSingle(param);//获取子表信息
			if ("0".equals(sort.getSortStatus()) || "0".equals(subSort.getSortStatus())) {
				entity.setMessage(MessageUtil.getMessage("info-release-0002", new String[0], "数据信息不存在或者还没有启用,暂不能使用"));
				return entity;
			}
			if ("1".equals(sort.getSortStatistics()) || "1".equals(subSort.getSortStatistics())) {
				pvo.setParams("flagInfoStatistics", "true");
			}
			pvo.setParams(vo.getParams());
			pvo.setParams("mainSortCode", sort.getSortId());
			pvo.setParams("subSortCode", subSort.getSortId());
			vo.setParams("mainTableName", sort.getInfoTableName());
			vo.setParams("subTableName", subSort.getInfoTableName());
			pvo.setParams("mainTableName", sort.getInfoTableName());
			pvo.setParams("subTableName", subSort.getInfoTableName());
			//pvo.setParams("params", vo.getParams());
			if (Validator.isNotNull(String.valueOf(vo.getParams("dynamicSql")))) {//直接执行sql查询
				pvo.setParams("dyncSql", String.valueOf(vo.getParams("dynamicSql")));
			}
			pvo.setParams("DatabaseType",
					MessageUtil.getDatabastType(StrUtil.doNull(sort.getSysName(), "plateform"), ""));
			Object obj = doInvoke(pvo);
			entity.setEntity(obj);
			entity.setMessage("方法执行成功");//////////////////////
		} else {
			entity.setMessage(MessageUtil.getMessage("info-release-0001", new String[0], "执行方法缺少必要参数"));
		}
		log.info("请求参数:" + vo.getParams());
		return entity;
	}

	protected abstract Object doInvoke(ParamsVo vo);

	protected String getDynicSql(ParamsVo vo, int sqlType, String sortId, String tableName) {
		StringBuffer sb = new StringBuffer();
		MethodParam param = new MethodParam("ByProperty", "", "", PubMetadata.class.getName());
		Map map = vo.getParams();
		List<PubMetadata> mlist = null;
		if (1 == sqlType || 2 == sqlType || 3 == sqlType) {//新增,修改,删除
			param.setParams("sortId", sortId);
			mlist = pubMetadataDao.select(param);
			if (Validator.isNotNull(String.valueOf(map.get("infoId")))) {
				map.put("subId", map.get("infoId"));
			}
			map.put("tableName", tableName);
		} else {
			param.setParams("sortId", String.valueOf(vo.getParams("mainSortCode")));
			mlist = pubMetadataDao.select(param);
			param.setParams("sortId", String.valueOf(vo.getParams("subSortCode")));
			List<PubMetadata> slist = pubMetadataDao.select(param);
			if (Validator.isEmpty(mlist))
				mlist = slist;
			else
				mlist.addAll(slist);
			vo.setParams("metadatas", mlist);
		}

		if (!Validator.isEmpty(mlist)) {
			//Map params = (Map) map.get("params");
			//            String dbType = ConfigUtil.getInstance()
			//                    .getValueByKey("jdbc.properties", "database_type");
			String dbType = String.valueOf(vo.getParams("DatabaseType"));
			if ("oracle".equals(dbType)) {
				sb.append(sqlForOracle(mlist, map, sqlType, dbType));
			} else if ("sqlserver".equals(dbType)) {
				sb.append(sqlForOracle(mlist, map, sqlType, dbType));
			} else if ("mysql".equals(dbType)) {
				sb.append(sqlForOracle(mlist, map, sqlType, dbType));
			}
		}
		log.info("getPubSql=" + sb.toString());
		return sb.toString();
	}

	/**
	 * description:  拼装待执行sql
	 * 插入、修改、删除执行两次
	 */
	private String sqlForOracle(List<PubMetadata> metadata, Map<String, String> map, int sqlType, String dbType) {
		StringBuffer sb = new StringBuffer("");
		StringBuffer sb2 = new StringBuffer("");
		String tid = "";
		int i = 0;

		switch (sqlType) {
		case 1://新增
			sb.append("insert into " + map.get("tableName") + "( ");
			sqlForInsert(i, sb, sb2, metadata, map, dbType);
			sb.append(" ) values(" + sb2.toString() + ")");
			break;
		case 2://修改
			sb.append("UPDATE " + map.get("tableName") + " SET ");
			tid = sqlForEdit(i, tid, sb, sb2, metadata, map, dbType);
			if (Validator.isNull(sb2.toString())) {//没有要修改的
				return "";
			}
			sb.append(sb2.toString());
			sb.append(" where " + tid);
			break;
		case 3://删除
			sb.append("Delete from " + map.get("tableName"));
			for (PubMetadata pm : metadata) {
				if (Validator.isNotNull(map.get(pm.getDataAttr()))) {
					sb2.append(sqlWhere2(pm, map.get(pm.getDataAttr()), i));
					i++;
				}
			}
			if (sb2.length() > 0) {
				sb.append(" where " + sb2.toString());
			}
			break;
		case 4://查询
			sb.append("select ");
			String orberBy = "";
			int k = 0;
			String sin = "@";
			for (PubMetadata pm : metadata) {
				if (Validator.isNotNull(pm.getReserved1())) {
					orberBy += pm.getDataShortName() + " " + pm.getReserved1() + ",";
				}
				String fix = "";
				if (map.get("mainTableName").indexOf(pm.getSortId()) != -1) {
					fix = "m.";
				} else {
					fix = "s.";
				}
				if (k == 0) {
					sb.append(fix + pm.getDataShortName() + " as \"" + pm.getSortId() + sin
							+ InfoMap.exChange(pm.getDataAttr()) + "\"");//pm.getDataAttr());
				} else {
					sb.append("," + fix + pm.getDataShortName() + " as \"" + pm.getSortId() + sin
							+ InfoMap.exChange(pm.getDataAttr()) + "\"");//pm.getDataAttr());
				}
				if (Validator.isNotNull(map.get(pm.getDataAttr()))) {
					sb2.append(sqlWhere(pm, map.get(pm.getDataAttr()), i, fix));
					i++;
				}
				k++;
			}
			sb.append(" from " + map.get("mainTableName") + " m," + map.get("subTableName")
					+ " s  where m.info_Id=s.sub_Id");
			if (sb2.length() > 0) {
				sb.append(sb2.toString());
			}
			//自定义排序
			if (Validator.isNotNull(map.get("orderby"))) {
				sb.append(" order by " + map.get("orderby"));
			} else {
				if (Validator.isNotNull(orberBy)) {
					sb.append(" order by " + orberBy.substring(0, orberBy.length() - 1));
				}
			}
			break;
		case 5://取记录数
			sb.append("select");
			for (PubMetadata pm : metadata) {
				String fix = "";
				if (map.get("mainTableName").indexOf(pm.getSortId()) != -1) {
					fix = "m.";
				} else {
					fix = "s.";
				}
				if (Validator.isNotNull(map.get(pm.getDataAttr()))) {
					sb2.append(sqlWhere(pm, map.get(pm.getDataAttr()), i, fix));
					i++;
				}
			}
			sb.append(" m.info_Id from " + map.get("mainTableName") + " m," + map.get("subTableName")
					+ " s where m.info_Id=s.sub_Id");
			if (sb2.length() > 0) {
				sb.append(" where " + sb2.toString());
			}
			break;
		}
		return sb.toString();
	}

	/**
	 * description:  拼插入sql
	 */
	private void sqlForInsert(int i, StringBuffer sb, StringBuffer sb2, List<PubMetadata> metadata,
			Map<String, String> map, String dbType) {
		for (PubMetadata pm : metadata) {
			if (Validator.isNotNull(map.get(pm.getDataAttr()))) {
				if (i == 0) {
					sb.append(pm.getDataShortName());
					if ("1".equals(pm.getDataType()) || "2".equals(pm.getDataType()) || "3".equals(pm.getDataType())) {
						sb2.append(map.get(pm.getDataAttr()));
					} else if ("6".equals(pm.getDataType())) {
						sb2.append(dateSql(map.get(pm.getDataAttr()), dbType));
					} else {
						sb2.append("'" + map.get(pm.getDataAttr()) + "'");
					}
				} else {
					sb.append("," + pm.getDataShortName());
					if ("1".equals(pm.getDataType()) || "2".equals(pm.getDataType()) || "3".equals(pm.getDataType())) {
						sb2.append(" ," + map.get(pm.getDataAttr()));
					} else if ("6".equals(pm.getDataType())) {
						sb2.append("," + dateSql(map.get(pm.getDataAttr()), dbType));
					} else {
						sb2.append(" ,'" + map.get(pm.getDataAttr()) + "'");
					}
				}
				i++;
			}
		}
	}

	/**
	 * description:  拼修改sql
	 */
	private String sqlForEdit(int i, String tid, StringBuffer sb, StringBuffer sb2, List<PubMetadata> metadata,
			Map<String, String> map, String dbType) {
		for (PubMetadata pm : metadata) {
			String fix = "";
			if (map.get("mainTableName").indexOf(pm.getSortId()) != -1) {
				fix = "m.";
			} else {
				fix = "s.";
			}
			if (Validator.isNotNull(map.get(pm.getDataAttr()))) {
				if ("1".equals(pm.getDataRestrict())) {
					tid = fix + pm.getDataShortName() + "='" + map.get(pm.getDataAttr()) + "'";
					continue;
				}
				if (i == 0) {
					if ("1".equals(pm.getDataType()) || "2".equals(pm.getDataType()) || "3".equals(pm.getDataType())) {
						sb2.append(fix + pm.getDataShortName() + "=" + map.get(pm.getDataAttr()));
					} else if ("6".equals(pm.getDataType())) {
						sb2.append(fix + pm.getDataShortName() + "=" + dateSql(map.get(pm.getDataAttr()), dbType));
					} else {
						sb2.append(fix + pm.getDataShortName() + "='" + map.get(pm.getDataAttr()) + "'");
					}
				} else {
					if ("1".equals(pm.getDataType()) || "2".equals(pm.getDataType()) || "3".equals(pm.getDataType())) {
						sb2.append(fix + pm.getDataShortName() + "=" + map.get(pm.getDataAttr()));
					} else if ("6".equals(pm.getDataType())) {
						sb2.append(
								"," + fix + pm.getDataShortName() + "=" + dateSql(map.get(pm.getDataAttr()), dbType));
					} else {
						sb2.append(" ," + fix + pm.getDataShortName() + "='" + map.get(pm.getDataAttr()) + "'");
					}
				}
				i++;
			}
		}
		return tid;
	}

	private String dateSql(String value, String dbType) {
		String sql = "";
		if ("oracle".equals(dbType)) {
			sql = "to_date('" + value + "','yyyy-mm-dd hh24:mi:ss')";
		} else if ("sqlserver".equals(dbType)) {
			sql = "to_date('" + value + "','yyyy-mm-dd hh:mm:ss')";
		} else if ("mysql".equals(dbType)) {
			sql = "to_date('" + value + "','yyyy-mm-dd hh:mi:ss')";
		}
		return sql;//"'" + value + "'";
	}

	/**
	 * description:  拼装待执行sql条件
	 */
	private String sqlWhere(PubMetadata pm, String value, int num, String fix) {
		String result = "";
		if ("1".equals(pm.getDataType()) || "2".equals(pm.getDataType()) || "3".equals(pm.getDataType())) {
			result = " and " + fix + pm.getDataShortName() + "=" + value;
		} else {
			if (value.startsWith("like '%") || value.startsWith("in (")) {
				result = " and " + fix + pm.getDataShortName() + " " + value;
			} else {
				result = " and " + fix + pm.getDataShortName() + "='" + value + "'";
			}
		}
		return result;
	}

	/**
	 * description:  拼装待执行sql条件
	 */
	private String sqlWhere2(PubMetadata pm, String value, int num) {
		String result = "";
		if (num == 0) {
			if ("1".equals(pm.getDataType()) || "2".equals(pm.getDataType()) || "3".equals(pm.getDataType())) {
				if (value.startsWith("between")) {
					result = pm.getDataShortName() + " " + value;
				} else {
					result = pm.getDataShortName() + "=" + value;
				}
			} else {
				if (value.startsWith("like '%") || value.startsWith("in (")) {
					result = pm.getDataShortName() + " " + value;
				} else {
					result = pm.getDataShortName() + "='" + value + "'";
				}
			}
		} else {
			if ("1".equals(pm.getDataType()) || "2".equals(pm.getDataType()) || "3".equals(pm.getDataType())) {
				if (value.startsWith("between")) {
					result = " and " + pm.getDataShortName() + " " + value;
				} else {
					result = " and " + pm.getDataShortName() + "=" + value;
				}
			} else {
				if (value.startsWith("like '%") || value.startsWith("in (")) {
					result = " and " + pm.getDataShortName() + " " + value;
				} else {
					result = " and " + pm.getDataShortName() + "='" + value + "'";
				}
			}
		}
		return result;
	}

	public void setPubMetadataDao(IDao pubMetadataDao) {
		this.pubMetadataDao = pubMetadataDao;
	}

	public void setInfoReleaseManager(InfoReleaseManager infoReleaseManager) {
		InfoReleaseManager = infoReleaseManager;
	}
}
